#include<iostream>
#include<unistd.h>
#include<cstdio>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/fcntl.h>
#include<pthread.h>
#include<cassert>
#include<vector>
#include<string>
#include<cstdlib>
#include<ctime>
#include"myThread.hpp"
#include"Mutex.hpp"
#include"BlockQueue.hpp"
#include"Task.hpp"







// 基于阻塞队列的生产消费模型： 多生产多消费，单生产单消费单存储的两个生产消费模型的联动

// template<class T ,class T2 ,size_t maxsize=5>
// struct Data  //用于传给线程的数据
// {
//     Data(BlcokQueue<T,maxsize>* pbq,BlcokQueue<T2,maxsize>* sbq,std::string name)
//     :_pbq(pbq),_sbq(sbq),_name(name)
//     {}
    
//     BlcokQueue<T , maxsize>* _pbq;
//     std::string _name;
//     BlcokQueue<T2 , maxsize>* _sbq;
// };

// void* productor_start_routine(void* arg) //生产者
// {
//     Data<Task,storeTask>* pdata=(Data<Task,storeTask>*)arg;
//     BlcokQueue<Task>*bq=pdata->_pbq;
//     BlcokQueue<storeTask>*sbq=pdata->_sbq;
//     char ops[]="+-*\%";
//     while(1) // 生产者需要做的就是不断生产数据
//     {
//         //先用简单的数据来模拟，测试一下生产消费的逻辑是否有问题
//         int x = rand()%100; //生产数据 
//         int y = rand()%100;
//         char op = ops[rand()%5];
//         Task t(x,y,op,mymath);
//         bq->push(t); //放数据
//         std::cout<<pdata->_name<<"  生产了一个任务 : "<< t.tostring() <<std::endl;
//         //生产完一个休息一下
//         usleep(1000);
//     }
//    return nullptr;
// }

// void* consumer_start_routine(void* arg) //消费者
// {
//     Data<Task,storeTask>* pdata=(Data<Task,storeTask>*)arg;
//     BlcokQueue<Task>*bq=pdata->_pbq;
//     BlcokQueue<storeTask>*sbq=pdata->_sbq;

//     while(1) // 消费者需要做的就是不断消费数据
//     {
//         Task t;
//         pdata->_pbq->pop(&t); //拿数据
//         std::cout<<pdata->_name<<"  消费了一个任务，结果是: "<< t() <<std::endl;
//         //构建一个存储任务
//         storeTask st(t(),store_func);
//         sbq->push(st);
//         std::cout<<pdata->_name<<"推送了一个存储任务"<<std::endl;
//         usleep(100000);
//     }
//     return nullptr;
// }

// void* store_start_routine(void* arg) //存储者
// {
//     Data<Task,storeTask>* pdata=(Data<Task,storeTask>*)arg;
//     BlcokQueue<Task>*bq=pdata->_pbq;
//     BlcokQueue<storeTask>*sbq=pdata->_sbq;
//     while(1)
//     {   
//         storeTask st;
//         sbq->pop(&st);
//         st();
//         std::cout<<pdata->_name<<"完成了一个存储任务"<<std::endl;
//         usleep(10000);
//     }

//     return nullptr;
// }





// int main()
// {
//     srand((unsigned int)time(nullptr)); //先用随机数模拟数据
//     //首先我们需要有一个阻塞队列
//     BlcokQueue<Task>* bq =new BlcokQueue<Task>; 
//     BlcokQueue<storeTask>* storebq =new BlcokQueue<storeTask>; 
//     //然后创建两个线程
//     //pthread_t cons[5],prod[5];
//     pthread_t cons,prod,store;

//     int connum=1;
//     // for(int i=0;i<5;++i)
//     // {
//     //     char* conbuffer = new char[64];
//     //     snprintf(conbuffer,64,"consumer thread %d",connum++);
//     //     Data<Task>* condata=new Data<Task>(bq,conbuffer);
//     //     pthread_create(cons+i,nullptr,consumer_start_routine,(void*)condata); //消费者线程
//     // }
//      char conbuffer[64];
//      snprintf(conbuffer,sizeof conbuffer,"consumer thread %d",connum++);
//      Data<Task,storeTask>* condata=new Data<Task,storeTask>(bq,storebq,conbuffer);
//      pthread_create(&cons,nullptr,consumer_start_routine,(void*)condata); //消费者线程

//     int prodnum=1;
//     // for(int i=0;i<5;++i)
//     // {
//     //     char* prodbuffer = new char[64];
//     //     snprintf(prodbuffer,64,"productor thread %d",prodnum++);
//     //     Data<Task>* proddata=new Data<Task>(bq,prodbuffer);
//     //     pthread_create(prod+i,nullptr,productor_start_routine,(void*)proddata); //消费者线程
//     // }

//      char prodbuffer[64];
//      snprintf(conbuffer,sizeof prodbuffer,"consumer thread %d",prodnum++);
//      Data<Task,storeTask>* proddata=new Data<Task,storeTask>(bq,storebq,prodbuffer);
//      pthread_create(&prod,nullptr,productor_start_routine,(void*)proddata); //生产者线程


  
//     int storenum=1;
//     char stobuffer[64];
//     snprintf(stobuffer,sizeof stobuffer,"store thread %d",storenum++);
//     Data<Task,storeTask>* stodata = new Data<Task,storeTask>(bq,storebq,stobuffer);
//     pthread_create(&store,nullptr,store_start_routine,(void*)stodata); //存储者线程

//     while(1) sleep(1); //主线程不退出

//     // for(int i=0;i<5;++i)
//     // {
//     //     pthread_join(cons[i],nullptr);
//     // }
//     // for(int i=0;i<5;++i)
//     // pthread_join(prod[i],nullptr);
//     delete bq;
//     return 0;
// }





// int tickets=100;
// pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
// void* buyticket(void*arg)
// {
//     const char*name=static_cast<const char*>(arg);
//     while(1)
//     {
//         //将临界区封装成代码块
//         {
//             pthread_mutex_lock(&mutex);
//             //临界区的开始
//             //不管怎么说，进入临界区都先去条件变量下等待，直到别的线程唤醒
//             pthread_cond_wait(&cond,&mutex);
//             if(tickets>0)
//             {
//                 tickets--;
//                 std::cout<<name <<"抢到了第"<<tickets<<"张票"<<std::endl; 
//             }
//             else
//             {         
//                 break;
//             }       
//             pthread_mutex_unlock(&mutex);

//         }
//     }
//     delete[] name;
//     return nullptr;
// }

// int main()
// {
//     pthread_t tids[4];
//     for(int i=0;i<4;++i)
//     {
//         char* name = new char[64] ;
//         snprintf(name,64,"Thread %d",i+1);
//         pthread_create(tids+i,nullptr,buyticket,(void*)name);
//     }
//     while(1)
//     {
//         pthread_cond_signal(&cond); //主线程每隔一段时间唤醒一个该条件变量下的线程
//         usleep(10000);
//     }

//     for(int i=0;i<4;++i)
//     {
//         pthread_join(tids[i],nullptr);
//     }
//     return 0;
// }



// int tickets=100;
// pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

// void* buyticket(void*arg)
// {
//     const char*name=static_cast<const char*>(arg);
//     while(1)
//     {
//         //将临界区封装成代码块
//         {
//             //Mutex m(mutex);
//             //临界区的开始
//             pthread_mutex_lock(&mutex);
//             pthread_mutex_lock(&mutex);
//             if(tickets>0)
//             {
//                 //usleep(10000);
//                 tickets--;
//                 std::cout<<name <<"抢到了第"<<tickets<<"张票"<<std::endl; 
//                 usleep(10000);
//                 //访问完解锁
//                 //pthread_mutex_unlock(&mutex);
//                 usleep(10000);
//             }
//             else
//             {   
//                 //运行到这里也说明前面肯定拿到锁了，那么也需要解锁
//                 //pthread_mutex_unlock(&mutex);        
//                 break;
//             }
//             //pthread_mutex_unlock(&mutex);        
//         }
//     }
//     delete[] name;
//     return nullptr;
// }

// int main()
// {
//     pthread_t tids[4];
//     for(int i=0;i<4;++i)
//     {
//         char* name = new char[64] ;
//         snprintf(name,64,"Thread %d",i+1);
//         pthread_create(tids+i,nullptr,buyticket,(void*)name);
//     }
//     for(int i=0;i<4;++i)
//     {
//         pthread_join(tids[i],nullptr);
//     }
//     return 0;
// }






// void*start_routine(void* arg)
// {
//     const char* name=static_cast<const char*>(arg);
//     while(1)
//     {
//         std::cout<<name<<std::endl;
//         sleep(1);
//     }
//     return nullptr;
// }

// int main()
// {
//     Thread t(start_routine,(void*)"thread 1");
//     t.start();
//     while(1)
//     {
//         sleep(1);
//     }

//     return 0;
// }




// __thread int cnt=0;

// void* start_routine(void* arg)
// {
//     const char* name=static_cast<const char*>(arg);     
//     while(1)
//     {
//         std::cout<<name << " --> cnt:"<<cnt<<"----&cnt:"<<&cnt <<"---对cnt进行++操作"<<std::endl;
//         cnt++;
//         sleep(1);
//     }
//     return nullptr;
// }

// int main()
// {
//     pthread_t tid;
//     pthread_create(&tid,nullptr,start_routine,(void*)"Thread 1");

//     while(1)
//     {   
//         std::cout<<"main thread ->cnt : "<<cnt<<"----&cnt:" <<&cnt<<std::endl;
//         sleep(1);
//     }
//     return 0;
// }



// class Ret
// {
// public:
//     int _code;
//     std::string _reason;
// };


// void* start_routine(void* arg)
// {
//     //sleep(3);
//     //pthread_t selfid =*(static_cast<pthread_t*> (arg));
//     // pthread_cancel(selfid);
//     // Ret* ret = new Ret;
//     // ret->_code =6;
//     // ret->_reason="Exited!";
//     // pthread_exit((void*)ret);
//     // std::cout<<"并没有取消成功！"<<std::endl;
//     // fflush(stdout);
//     pthread_detach(pthread_self());
//     return (void*) 66;
// }


// int main()
// {
//     pthread_t tid;
//     // pthread_create(&tid,nullptr,start_routine,nullptr);
//     pthread_create(&tid,nullptr,start_routine,(void*)&tid);
//     //sleep(1);
//     //pthread_cancel(tid);
//     sleep(1);
//     void* ret;
//     int n=pthread_join(tid,&ret);
//     if(n!=0)
//     {
//         std::cout<<"等待失败，错误码是:"<<n<<std::endl;
//         exit(1);
//     }
//     (void)n;
    
//     //Ret* pr=static_cast<Ret*>(ret);
//     //std::cout<<"线程退出码:"<<pr->_code<<"--描述:"<<pr->_reason<<std::endl;

//     std::cout<<"线程退出结果:"<<(long long)ret<<std::endl;
//     return 0;
// }





// void* start_routine(void* arg)
// {
//     int cnt=0;
//     while(1)
//     {
//         std::cout<<"New Thread : "<<cnt++<<std::endl;
//         sleep(1);
//         if(cnt==5)
//         {
//             std::cout<<"New Thread Exit!"<<std::endl;
//             pthread_exit(nullptr);  // 出口
//         }
//     }
//     return nullptr;  // 出口
// }
// int main()
// {
//     pthread_t tid;
//     pthread_create(&tid,nullptr,start_routine,nullptr);
//     sleep(10);
//     std::cout<<"10秒已到，主线程要退出喽!"<<std::endl;
//     return 0;
// }


// class Data
// {
// public:
//     pthread_t _tid;
//     std::string _name;
// };


// void* start_routine(void*arg)
// {
//     // const char* name=static_cast<const char*> (arg);
//     Data* pd=static_cast<Data*>(arg);
//     while(1)
//     {
//         std::cout<<"name: "<<pd->_name<<" ---- tid"<<pd->_tid<<std::endl;
//         sleep(1);
//     }
//     delete pd;
//     return nullptr;
// }


// int main()
// {
//     std::vector<pthread_t> tids(5,0);
//     for(int i=0;i<5;++i)
//     {
//         char name[64];
//         //char*name=new char[64];
//         snprintf(name, 64 , "this is Thread %d",i+1);
//         Data* pd = new Data;
//         pd->_name=name;
//         pthread_create(&pd->_tid,nullptr,start_routine,(void*)pd);
//     }

//     while(1)
//     {
//         std::cout<<"this is main thread"<<std::endl;
//         sleep(1);
//     }

//     return 0;
// }



// int* pa;

// void* start_routine(void*args)
// {
//     int a=10;
//     pa=&a;
//     while(1)
//     {
//         std::cout<<"a:"<<a<<"  &a:"<<&a<<std::endl;
//         sleep(1);
//     }
//     return nullptr; 
// }

// int main()
// {
//     pthread_t tid;
//     int ret=pthread_create(&tid,nullptr,start_routine,nullptr);
//     assert(ret==0);
//     (void)ret;

//     while(1)
//     {
//         std::cout<<"main  pa:"<<pa<<"a:"<< *pa <<std::endl; //如果 *pa 不报错，就说明能够访问，如果报错就说明不能访问
//         //*pa++;
//         sleep(1);
//     }

//     return 0;
// }


// int g_val=0;

// void*  start_routine (void* arg)
// {
//     const char*name = static_cast<const char*>(arg);
    
//     while(1)
//     {
//         //std::cout<<name <<"is running "<<std::endl;  //新线程不断打印
//         std::cout<< name <<":  g_val:"<<g_val <<"  &g_val:"<<&g_val<<std::endl;
//         g_val++;
//         sleep(1);
//     } 
// }


// int main()
// {
//    pthread_t tid;
    
//     int ret=pthread_create(&tid,nullptr,start_routine,(void*)"thread 1");
//     assert(ret==0);
//     (void) ret;
//     while(1) //主线程不退出，观察新线程
//     {
//         //std::cout<< "main thread is running" << std::endl;
//         // printf("tid:%d ,%x\n",tid,tid);
//         std::cout<<"main thread :  "<<"g_val:"<<g_val <<"  &g_val:"<<&g_val<<std::endl;
//         sleep(1);
//     }

//     return 0;
// }
